#ifndef __Iterator_Range_H__
#define __Iterator_Range_H__

namespace PVM
{
	template <typename T>
	class iterator_range
	{
		T mBegin, mEnd;
		
	public:
		iterator_range(T b, T e): mBegin(b), mEnd(e) {}
		T begin() const {return mBegin;}
		T end() const {return mEnd;}
		bool empty() const {return mBegin == mEnd;}
		
		bool equal(const iterator_range& other) const
		{
			return mBegin == other.mBegin && mEnd == other.mEnd;
		}
		
		bool operator==(const iterator_range& rhs) const
		{
			return equal(rhs);
		}
		
		bool operator!=(const iterator_range& rhs) const
		{
			return !operator==(rhs);
		}
		
		typedef T iterator;
		
		typedef T const_iterator;
		
		typedef iterator_range<T> type;
	};
	
	template<typename T>
	struct VectorRange : public iterator_range<typename T::iterator>::type
	{
		VectorRange(T& c)
		: iterator_range<typename T::iterator>::type(c.begin(), c.end())
		{}
		
		VectorRange(typename T::iterator b, typename T::iterator e)
		: iterator_range<typename T::iterator>::type(b, e)
		{}
		
		bool operator==(const VectorRange& rhs) const
		{
			return equal(rhs);
		}
		
		bool operator!=(const VectorRange& rhs) const
		{
			return !equal(rhs);
		}
		
		operator VectorIterator<T>() 
		{
			return VectorIterator<T>(this->begin(), this->end());
		}
		
		operator ConstVectorIterator<T>()
		{
			return ConstVectorIterator<T>(this->begin(), this->end());
		}
	};
	
	template<typename T>
	struct ConstVectorRange : public iterator_range(typename T::const_iterator)::type
	{
		ConstVectorRange(const T& c)
		: iterator_range<typename T::const_iterator>::type(c.begin(), c.end())
		{}
		
		ConstVectorRange(typename T::iterator b, typename T::iterator e)
		: iterator_range<typename T::const_iterator>::type(b, e)
		{}
		
		ConstVectorRange(typename T::const_iterator b, typename T::const_iterator e)
		: iterator_range<typename T::const_iterator>::type(b, e)
		{}
		
		ConstVectorRange(const VectorRange<T>& rhs)
		: iterator_range<typename T::const_iterator>::type(rhs.begin(), rhs.end())
		{}
		
		bool operator==(const ConstVectorRange& rhs) const
		{
			return equal(rhs);
		}
		
		bool operator!=(const ConstVectorRange& rhs) const
		{
			return !equal(rhs);
		}
		
		operator ConstVectorIterator<T>()
		{
			return ConstVectorIterator<T>(this->begin(), this->end());
		}
	};
	
	template<typename T>
	struct MapRange : public iterator_range<typename T::iterator>::type
	{
		MapRange(T& c)
		: iterator_range<typename T::iterator>::type(c.begin(), c.end())
		{}
		
		MapRange(typename T::iterator b, typename T::iterator e)
		: iterator_range<typename T::iterator>::type(b, e)
		{}
		
		bool operator==(const MapRange& rhs) const
		{
			return equal(rhs);
		}
		
		bool operator!=(const MapRange& rhs) const
		{
			return !equal(rhs);
		}
		
		operator MapIterator<T>()
		{
			return MapIterator<T>(this->begin(), this->end());
		}
		
		operator ConstMapIterator<T>()
		{
			return ConstMapIterator<T>(this->begin(), this->end());
		}
	};
	
	template<typename T>
	struct ConstMapRange : public iterator_range<typename T::const_iterator>::type
	{
		ConstMapRange(const T& c)
		: iterator_range<typename T::const_iterator>::type(c.begin(), c.end())
		{}
		
		ConstMapRange(typename T::iterator b, typename T::iterator e)
		: iterator_range<typename T::const_iterator>::type(b, e)
		{}
		
		ConstMapRange(typename T::const_iterator b, typename T::const_iterator e)
		: iterator_range<typename T::const_iterator>::type(b, e)
		{}
		
		ConstMapRange(const MapRange<T>& rhs)
		: iterator_range<typename T::const_iterator>::type(rhs.begin(), rhs.end())
		{}
		
		bool operator==(const ConstMapRange& rhs) const
		{
			return equal(rhs);
		}
		
		bool operator!=(const ConstMapRange& rhs) const
		{
			return !equal(rhs);
		}
		
		operator ConstMapIterator<T>()
		{
			return ConstMapIterator<T>(this->begin(), this->end());
		}
	};
}

#endif
